package cn.mw.cmdb.util;

import cn.mw.cmdb.entity.AssetsCodeCacheDTO;
import cn.mw.cmdb.entity.ModelInfo;
import cn.mw.cmdb.service.impl.CmdbServiceManage;
import cn.mw.cmdb.service.impl.CustomModelServiceImpl;
import cn.mw.cmdb.service.impl.InstanceServiceImpl;
import cn.mw.components.mongodb.tool.CriteriaWrapper;
import cn.mw.microMonitorCommon.util.RedisUtils;
import cn.mw.microMonitorCommon.util.SpringUtils;
import com.google.common.base.Strings;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.data.mongodb.core.query.Query;

import java.text.SimpleDateFormat;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import static cn.mw.cmdb.util.ValConvertUtil.longValueConvert;
import static cn.mw.components.mongodb.entity.MongoPropertyType.strValueConvert;

public class AssetCodeGenerator {
    private static final String PREFIX = "S-";

    public static String getModelCodeCheck(String modelId) throws Exception {
        CmdbServiceManage cmdbServiceManage = SpringUtils.getBean(CmdbServiceManage.class);
        CustomModelServiceImpl customModelService = (CustomModelServiceImpl) cmdbServiceManage.getModelService(CustomModelServiceImpl.ID);
        List<ModelInfo> modelInfos = customModelService.getModelInfoByIncludesField(Arrays.asList(modelId), Arrays.asList(CMDBTool.getFieldName(ModelInfo::getModelCode)));
        if (CollectionUtils.isNotEmpty(modelInfos) && modelInfos.get(0) != null) {
            ModelInfo modelInfo = modelInfos.get(0);
            String modelCode = modelInfo.getModelCode();
            if (!Strings.isNullOrEmpty(modelCode)) {
                return modelCode;
            }
        }
        return null;
    }


    public static boolean checkModelCodeMatch(String assetsCodingPrefix,String value){
        String threeLevelCode = "";
        //四级编码
        String fourLevelCode = "00";
        if (assetsCodingPrefix.length() == 6) {
            fourLevelCode = "00";
        } else if (assetsCodingPrefix.length() == 8) {
            fourLevelCode = assetsCodingPrefix.substring(assetsCodingPrefix.length() - 2);
            threeLevelCode = assetsCodingPrefix.substring(0, 6);
        }
        String pattern = threeLevelCode + "-\\d{6}-" + fourLevelCode;
        Pattern r = Pattern.compile(pattern);
        Matcher matcher = r.matcher(value);
        return matcher.find();
    }




    public static Map<String, String> getBatchModelCode(List<String> modelIds) throws Exception {
        CmdbServiceManage cmdbServiceManage = SpringUtils.getBean(CmdbServiceManage.class);
        CustomModelServiceImpl customModelService = (CustomModelServiceImpl) cmdbServiceManage.getModelService(CustomModelServiceImpl.ID);
        List<ModelInfo> modelInfos = customModelService.getModelInfoByIncludesField(modelIds, Arrays.asList(CMDBTool.getFieldName(ModelInfo::getModelCode), CMDBTool.getFieldName(ModelInfo::getId)));
        Map<String, String> maps = new HashMap<>();
        if (CollectionUtils.isNotEmpty(modelInfos)) {
            for (ModelInfo modelInfo : modelInfos) {
                String modelCode = modelInfo.getModelCode();
                String modelId = modelInfo.getId();
                if (!Strings.isNullOrEmpty(modelCode)) {
                    maps.put(modelId, modelCode);
                }
            }
        }
        return maps;
    }


    public static String generateAssetCode(String modelId) throws Exception {
        String modelCode = getModelCodeCheck(modelId);
        String assetCodeStr = getIMDateId(modelCode);
        return assetCodeStr;
    }


    /**
     * 将编码缓存到redis中，每次获取时自动加1
     *
     * @param modelCode
     * @return
     */
    public static String getIMDateId(String modelCode) {
        if (Strings.isNullOrEmpty(modelCode)) {
            return null;
        }
        RedisUtils redisUtil = SpringUtils.getBean(RedisUtils.class);
        //四级编码
        String fourLevelCode = "00";
        if (modelCode.length() == 6) {
            fourLevelCode = "00";
        } else if (modelCode.length() == 8) {
            fourLevelCode = modelCode.substring(modelCode.length() - 2);
            modelCode = modelCode.substring(0, 6);
        } else {
            return null;
        }
        String prefix = PREFIX + modelCode;
        String dateKey = "cmdb::date:" + modelCode + fourLevelCode;
        String numKey = "cmdb::num:" + modelCode + fourLevelCode;
        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMM");
        String nowStr = sdf.format(new Date());
        if (!redisUtil.hasKey(numKey)) {
            redisUtil.set(numKey, 000000);
        }
        if (!redisUtil.hasKey(dateKey)) {
            redisUtil.set(dateKey, nowStr);
        } else {
            String redisDate = redisUtil.get(dateKey).toString();
            if (!redisDate.equals(nowStr)) {
                redisUtil.set(numKey, 000000);
                redisUtil.set(dateKey, nowStr);
            }
        }
        Long suffixNum = redisUtil.incrBy(numKey, 1);
        return prefix + "-" + nowStr + "-" + fourLevelCode + String.format("%06d", suffixNum);
    }

    public static void setRedisMaxValByAssetCode(String modelCode, int maxVal) throws Exception {
        int redisVal = maxVal;
        if (Strings.isNullOrEmpty(modelCode)) {
            return;
        }
        //四级编码
        String fourLevelCode = "00";
        if (modelCode.length() == 6) {
            fourLevelCode = "00";
        } else if (modelCode.length() == 8) {
            fourLevelCode = modelCode.substring(modelCode.length() - 2);
            modelCode = modelCode.substring(0, 6);
        } else {
            return;
        }
        String prefix = PREFIX + modelCode;
        String dateKey = "cmdb::date:" + modelCode + fourLevelCode;
        String numKey = "cmdb::num:" + modelCode + fourLevelCode;
        RedisUtils redisUtil = SpringUtils.getBean(RedisUtils.class);
        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMM");
        String nowStr = sdf.format(new Date());
        Object redisObj = redisUtil.get(dateKey);
        String redisDate = strValueConvert(redisObj);
        if (!redisUtil.hasKey(numKey)) {
            redisUtil.set(numKey, 000000);
        }
        if (!redisUtil.hasKey(dateKey)) {
            redisUtil.set(dateKey, nowStr);
        } else {
            if (!redisDate.equals(nowStr)) {
                redisUtil.set(numKey, 000000);
                redisUtil.set(dateKey, nowStr);
            }
        }
        String queryField = prefix + "-" + nowStr + "-" + fourLevelCode;
        Long suffixNum = redisUtil.incrBy(numKey, 0);
        //最大值大于redis中的缓存值，才设置
        if (longValueConvert(redisVal) > suffixNum) {
            redisUtil.set(numKey, redisVal);
            //改变redis缓存值后，必须清除数据库中assetCode的缓存
            CmdbServiceManage cmdbServiceManage = SpringUtils.getBean(CmdbServiceManage.class);
            InstanceServiceImpl instanceService = (InstanceServiceImpl) cmdbServiceManage.getModelService(InstanceServiceImpl.ID);
            Query query = new Query();
            query.addCriteria(CriteriaWrapper.where(AssetsCodeCacheDTO::getAssetsCode).regex(queryField));
            instanceService.deleteAssetsCodeByQuery(query);
        }
    }

    public static String getFourLevelModelCode(String modelId) throws Exception {
        String modelCode = getModelCodeCheck(modelId);
        //四级编码
        String fourLevelCode = "00";
        if (modelCode.length() == 6) {
            fourLevelCode = "00";
        } else if (modelCode.length() == 8) {
            fourLevelCode = modelCode.substring(modelCode.length() - 2);
            modelCode = modelCode.substring(0, 6);
        } else {
            return "";
        }
        String fourModelCode = modelCode + "-" + fourLevelCode;
        return fourModelCode;
    }


    /**
     * 获取页面展示的资产编码
     *
     * @param modelId
     * @return
     */
    public static String getIMDateIdNoShow(String modelId) throws Exception {
        String assetsCodingPrefix = getAssetsCodingPrefix(modelId);
        if (Strings.isNullOrEmpty(assetsCodingPrefix)) {
            return null;
        }
        return assetsCodingPrefix + "xxxxxx";
    }

    public static String getAssetsCodingPrefix(String modelId) throws Exception {
        String modelCode = getModelCodeCheck(modelId);
        if (Strings.isNullOrEmpty(modelCode)) {
            return null;
        }
        //四级编码
        String fourLevelCode = "00";
        if (modelCode.length() == 6) {
            fourLevelCode = "00";
        } else if (modelCode.length() == 8) {
            fourLevelCode = modelCode.substring(modelCode.length() - 2);
            modelCode = modelCode.substring(0, 6);
        } else {
            return null;
        }
        String prefix = PREFIX + modelCode;
        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMM");
        String nowStr = sdf.format(new Date());
        return prefix + "-" + nowStr + "-" + fourLevelCode;
    }

    /**
     * 根据实物标签号的命名规则，解析出模型编码
     * //S-445566-202409-99000100 -> 44556699
     *
     * @param assetCode
     * @return
     */
    public static String getDeviceCodeByAssetsCode(String assetCode) {
        String modelCodeStr = "";
        //S-445566-202409-99000100
        if (!Strings.isNullOrEmpty(assetCode) && assetCode.length() >= 24) {
            String[] splitArr = assetCode.split("-");
            if (splitArr.length >= 4) {
                modelCodeStr = splitArr[1] + splitArr[3].substring(0, 2);
            }
        }
        return modelCodeStr;

    }
}

